#pragma once
#include <set>
#include <string>
#include "InetAddr.hpp"
namespace kzz
{
    class Command
    {
    public:
        Command()
        {
            _WhiteListCommand.insert("ls");
            _WhiteListCommand.insert("who");
            _WhiteListCommand.insert("pwd");
            // _WhiteListCommand.insert("who");
            // _WhiteListCommand.insert("who");
            // _WhiteListCommand.insert("who");
            // _WhiteListCommand.insert("who");
        }
        bool IsSafeCommand(const std::string &cmd)
        {
            return _WhiteListCommand.find(cmd) != _WhiteListCommand.end();
        }

        std::string Execute(const std::string &cmd, const InetAddr &client_addr)
        {
           
                if (!IsSafeCommand(cmd))
                {
                    LOG(LogLevel::DBUGER) << "命令不安全，不执行";
                  return "坏人";
                }
                //popen会创建一个子进程，生成一个管道，然后命令打印在管道中，返回值是管道
                //子进程的 stdout 会被重定向到管道，而不会直接打印到显示器
                //有些命令没有显示返回，如touch，但也确实执行了
                FILE* fp=popen(cmd.c_str(),"r");
                if(fp==nullptr)
                {
                    LOG(LogLevel::DBUGER) << "没有这个命令";
                   return  "没有这个命令";
                }
                std::string ret;
                char buffer[1024];

                while(fgets(buffer,sizeof(buffer),fp))
                {
                    ret+=buffer;
                }
                LOG(LogLevel::DBUGER)<<client_addr.Ip()<<" "<<client_addr.Port()<<"执行了命令，结果为"<<ret.c_str();
                return ret;
            
        }

        ~Command() {}

    private:
        std::set<std::string> _WhiteListCommand; // 命令白名单
    };
}